import {Dimensions, Platform, StyleSheet, Text, View} from 'react-native';
import React from 'react';
import FAIcon from 'react-native-vector-icons/FontAwesome5';
import {getRealSize, RequestCameraPermission, Touchable} from '../utils';
import PropTypes from 'prop-types';
import DocumentPicker from 'react-native-document-picker';
import {v4 as uuidv4} from 'uuid';
import RNFS from 'react-native-fs';
import _ from 'lodash';
import getPath from '@flyerhq/react-native-android-uri-path';
import {I18n} from '../reducers/intl';
import FastImage from 'react-native-fast-image';
import ImageZoomModal from './image-zoom-modal';
import {connectActionSheet} from "@expo/react-native-action-sheet";
import Toast from "./toast";
import * as RNImagePicker from "react-native-image-picker";
import Spinner from "./spinner";

export const UploadState = {
  STANDBY: 'standby', // 刚刚添加
  PENDING: 'pending', // 准备上传
  UPLOADING: 'uploading', // 上传中
  DONE: 'done', // 上传成功
  ERROR: 'error', // 上传出错
};

const imageOptions = [
  I18n.t('options.image.camera'),
  I18n.t('options.image.album'),
  I18n.t('options.image.file'),
  I18n.t('options.image.close'),
];

class FileUpload extends React.Component {
  static propTypes = {
    files: PropTypes.array.isRequired,
    onChange: PropTypes.func,
    onSuccess: PropTypes.func,
    onBegin: PropTypes.func,
    onProgress: PropTypes.func,
    addLabel: PropTypes.string,
    mode: PropTypes.string,
    width: PropTypes.number,
    disabled: PropTypes.bool,
  };

  static defaultProps = {
    files: [],
    onChange: () => {},
    onSuccess: () => {},
    onBegin: () => {},
    onProgress: () => {},
    disabled: false,
  };

  state = {
    imageModalVisible: false,
    imageIndex: 0,
    loading: false,
    percentage: 0
  };

  onShowPick = () => {
    this.props.showActionSheetWithOptions(
        {
          options: imageOptions,
          cancelButtonIndex: 3,
          destructiveButtonIndex: 3,
          textStyle: {flex: 1},
        },
        index => this.onPick(index),
    );
  };

  onPick = async (index) => {
    if (index === 0) {
      // console.log('index->', index)
      try {
        await RequestCameraPermission();
      } catch (e) {
        return Toast.show(e.message);
      }
      RNImagePicker.launchCamera(
          {
            mediaType: 'photo',
            includeBase64: false,
            maxHeight: Dimensions.get('screen').height,
            maxWidth: Dimensions.get('screen').width,
          },
          this.onUpload,
      );
    } else if (index === 1) {
      RNImagePicker.launchImageLibrary(
          {
            mediaType: 'photo',
            includeBase64: false,
            maxHeight: Dimensions.get('screen').height,
            maxWidth: Dimensions.get('screen').width,
          },
          this.onUpload,
      );
    } else if (index === 2) {
      try {
        const result = await DocumentPicker.pick({
          // copyTo: 'cachesDirectory',
          type: [DocumentPicker.types.allFiles],
        });
        const newFile = {
          ...result,
          uid: uuidv4(),
          state: UploadState.STANDBY,
        };
        await this.onUpload(newFile);
      } catch (err) {
        if (DocumentPicker.isCancel(err)) {
          // User cancelled the picker, exit any dialogs or menus and move on
          console.log('cancel');
        } else {
          throw err;
        }
      }
    }
  };

  uploadBegin = response => {
    const {jobId} = response;
    // console.log('UPLOAD HAS BEGUN! JobId: ' + jobId);
    // this.props.onBegin(jobId);
    this.setState({
      loading: true,
      percentage: 0
    })
  };

  uploadProgress = response => {
    const percentage = Math.floor(
      (response.totalBytesSent / response.totalBytesExpectedToSend) * 100,
    );
    if (percentage % 10 === 0) {
      // this.props.onProgress(response.jobId, percentage);
      this.setState({
        percentage
      })
      console.log(
          'UPLOAD PROGRESS ' + percentage + '%',
          // JSON.stringify(response),
      );
    }
  };

  onUpload = async newFile => {
    const {uploadUrl, token} = this.props;
    if (newFile.didCancel) {
      return;
    }

    /**
     {
        "fileName": "rn_image_picker_lib_temp_781f4e00-c99f-480e-93fe-915da2d8e8c4.jpg",
        "fileSize": 59986,
        "height": 181,
        "type": "image/jpeg",
        "uri": "file:///data/user/0/com.molarapp/cache/rn_image_picker_lib_temp_781f4e00-c99f-480e-93fe-915da2d8e8c4.jpg",
        "width": 392
    }
     {
        "name": "wx_camera_1647003229551.jpg",
        "size": 623099,
        "state": "standby",
        "type": "image/jpeg",
        "uid": "4983720f-3f4d-4b6b-bbc6-75bf2e04ea27",
        "uri": "content://com.android.providers.media.documents/document/image%3A54359"
    }
     * @type {*&{filetype, filename: *, filepath: string, name: string, state: string, type}}
     */

    const filepath = Platform.select({
      android: newFile.uri.startsWith('content') ? getPath(newFile.uri) : newFile.uri.replace('file://', ''),
      ios: newFile.uri.replace('file://', ''),
    });

    const uploadFile = {
      ...newFile,
      state: UploadState.PENDING,
      name: 'file',
      filename: newFile.name || newFile.fileName,
      filepath,
      filetype: newFile.type,
      type: newFile.type,
      uid: uuidv4()
    };
    console.log('file', newFile, uploadFile);
    const {jobId, promise} = RNFS.uploadFiles({
      toUrl: uploadUrl,
      files: [uploadFile],
      fields: {file: 'file'},
      binaryStreamOnly: false,
      method: 'POST',
      headers: {
        Authorization: `Bearer ${token}`,
      },
      begin: this.uploadBegin,
      beginCallback: this.uploadBegin, // Don't ask me, only way I made it work as of 1.5.1
      progressCallback: this.uploadProgress,
      progress: this.uploadProgress,
    });

    // this.props.onChange({...uploadFile, jobId, state: UploadState.PENDING});

    promise
      .then(response => {
        //HTTP response响应
        // console.log(response);
        if (response.statusCode == 200) {
          console.log('FILES UPLOADED!'); // response.statusCode状态码, response.headers响应header, response.body 响应body
          const payload = JSON.parse(response.body);
          this.props.onSuccess(_.get(payload, 'data'));
        } else {
          console.log('SERVER ERROR');
        }
      })
      .catch(err => {
        //HTTP请求异常
        if (err.description === 'cancelled') {
          // cancelled by user
        }
        // console.log(err);
      }).finally(() =>{
        this.setState({
          loading: false,
          percentage: 100
        })
      })
  };

  render() {
    const {files = [], addLabel, disabled} = this.props;
    const images = files.map(f => ({url: f.url}));
    return (
      <View>
        <Spinner
            textContent={`${this.state.percentage}`}
            visible={this.state.loading}
            onClose={() => this.setState({loading: false, percentage: 0})}
        />
        {files.map((f, index) => (
          <FileCard
            {...f}
            key={f.uid || f.id}
            isImage={() => isImage(f.filename)}
            onPress={() =>
              this.setState({imageIndex: index, imageModalVisible: true})
            }
          />
        ))}
        {!disabled && <AddCard onAddFile={this.onShowPick} label={addLabel} />}
        <ImageZoomModal
          visible={this.state.imageModalVisible}
          images={images}
          index={this.state.imageIndex}
          onClose={() => this.setState({imageModalVisible: false})}
        />
      </View>
    );
  }
}

// {props.state === UploadState.UPLOADING && (
//     <View style={Styles.fileProgress}>
//       <Pie progress={Number(props.rate || 0)} size={getRealSize(42)} />
//     </View>
// )}

const FileCard = props => (
  <View style={Styles.fileBox}>
    <View style={Styles.fileIcon}>
      {props.isImage ? (
        <Touchable onPress={() => props.onPress()}>
          <FastImage
            style={{width: getRealSize(48), height: getRealSize(48)}}
            source={{
              priority: FastImage.priority.normal,
              uri: props.url,
            }}
          />
        </Touchable>
      ) : (
        <FAIcon name="file" size={getRealSize(24)} color="#999999" />
      )}
    </View>
    <Text style={Styles.fileLabel} numberOfLines={1}>
      {props.filename}
    </Text>
  </View>
);

const isImage = fileName => {
  const flieArr = fileName.split('.');
  let suffix = flieArr[flieArr.length - 1];
  if (suffix != '') {
    suffix = suffix.toLocaleLowerCase();
    // 图片格式
    const imglist = ['png', 'jpg', 'jpeg', 'bmp', 'gif'];
    // 进行图片匹配
    return imglist.find(item => item === suffix);
  }
};

const AddCard = props => (
  <Touchable onPress={() => props.onAddFile()}>
    <View style={Styles.box}>
      <View style={Styles.addContent}>
        <FAIcon name="file-upload" size={getRealSize(24)} color="#999999" />
        <Text style={Styles.addLabel}>
          {props.addLabel || I18n.t('form.label.upload')}
        </Text>
      </View>
    </View>
  </Touchable>
);

AddCard.defaultProps = {
  onAddFile: () => {},
};

AddCard.propTypes = {
  onAddFile: PropTypes.func.isRequired,
};

export default connectActionSheet(FileUpload);

const Styles = StyleSheet.create({
  container: {
    flex: 1,
  },
  box: {
    height: getRealSize(64),
    backgroundColor: '#F6F6F6',
    borderRadius: getRealSize(4),
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: '#E8E8E8',
    alignItems: 'center',
    justifyContent: 'center',
  },
  addContent: {
    flexDirection: 'row',
    alignItems: 'center',
    paddingHorizontal: getRealSize(15),
  },
  addLabel: {
    marginLeft: getRealSize(16),
    fontSize: getRealSize(16),
    fontWeight: '400',
    color: '#999999',
    flex: 1,
  },
  fileProgress: {
    position: 'absolute',
  },
  fileBox: {
    flexDirection: 'row',
    alignItems: 'center',
    height: getRealSize(64),
    backgroundColor: '#F6F6F6',
    borderRadius: getRealSize(4),
    borderWidth: StyleSheet.hairlineWidth,
    borderColor: '#E8E8E8',
    marginBottom: getRealSize(15),
    paddingHorizontal: getRealSize(15),
  },
  fileIcon: {
    alignItems: 'center',
    justifyContent: 'center',
  },
  fileLabel: {
    marginLeft: getRealSize(16),
    fontSize: getRealSize(16),
    fontWeight: '400',
    color: '#999999',
    flex: 1,
  },
});
